/*
类(Class)：定义了一件事物的抽象特点，包含它的属性和方法
对象（Object）：类的实例，通过 new 生成
面向对象（OOP）的三大特性：封装、继承、多态
封装（Encapsulation）：将对数据的操作细节隐藏起来，只暴露对外的接口。外界调用端不需要（也不可能）知道细节，就能通过对外提供的接口来访问该对象，同时也保证了外界无法任意更改对象内部的数据
继承（Inheritance）：子类继承父类，子类除了拥有父类的所有特性外，还有一些更具体的特性
多态（Polymorphism）：由继承而产生了相关的不同的类，对同一个方法可以有不同的响应。比如 Cat 和 Dog 都继承自 Animal，但是分别实现了自己的 eat 方法。此时针对某一个实例，我们无需了解它是 Cat 还是 Dog，就可以直接调用 eat 方法，程序会自动判断出来应该如何执行 eat
存取器（getter & setter）：用以改变属性的读取和赋值行为
修饰符（Modifiers）：修饰符是一些关键字，用于限定成员或类型的性质。比如 public 表示公有属性或方法
抽象类（Abstract Class）：抽象类是供其他类继承的基类，抽象类不允许被实例化。抽象类中的抽象方法必须在子类中被实现
接口（Interfaces）：不同类之间公有的属性或方法，可以抽象成一个接口。接口可以被类实现（implements）。一个类只能继承自另一个类，但是可以实现多个接口
*/
// 1.类的定义
class Greeter {
    greeter : string;
    constructor(message:string = "默认魔术"){
        this.greeter = message;
    }
    greeting() {
      //类的方法
    };
}
let  grrent = new Greeter();
console.log(grrent);


// // 2.类的继承 默认为 public
// class  AnimalClass {
//     private  name : string;
//     public constructor(theName:string){
//         this.name = theName;
//     };
//     public  move(movedistance : number = 0){
//      console.log(`${this.name} 移动的距离是 ${movedistance}`);
//     };
// }
//
// class Shake extends AnimalClass{
//        constructor(name : string){
//             super(name);
//        };
//
//        move(movedistance:number =5){
//            console.log("Shake...");
//            super.move(movedistance);
//        }
// }
// class House extends AnimalClass{
//     constructor(name : string){
//         super(name);
//     };
//
//     move(movedistance:number =10){
//         console.log("House...");
//         super.move(movedistance);
//     }
// }
// let  shake = new Shake("蛇");
// let  house : AnimalClass = new House("马");
// shake.move();
// house.move(50);



// 3.类的修饰符 readonly修饰符 protected private  protected
/**
 *
 * typeScript 可以使用三种访问修饰符（Access Modifiers），分别是 public、private 和 protected。
 public 修饰的属性或方法是公有的，可以在任何地方被访问到，默认所有的属性和方法都是 public 的
 private 修饰的属性或方法是私有的，不能在声明它的类的外部访问
 protected 修饰的属性或方法是受保护的，它和 private 类似，区别是它在子类中也是允许被访问的
 * */

class  AnimalClass {
    //只有当前类可以访问
    private  _animalName : string;
    public constructor(theName:string){
        this._animalName = theName;
    };
    //子类可以访问
    protected  move(movedistance : number = 0){
     console.log(`${this._animalName} 移动的距离是 ${movedistance}`);
    };

    private jump(distance : number = 0){
        console.log(`${this._animalName} jummp ${distance}`);
    }

    set animalName(aName : string){
         this._animalName = aName;
    }

    get  animalName(){
        return this._animalName;
    }
}

class Shake extends AnimalClass{

        //静态属性  只有类可以访问
       static  point = {x : 0, y : 0};
       constructor(name : string){
            super(name);
       };

      move(movedistance:number =5){
        console.log("Shake...");
        super.move(movedistance);
      }

      culaturateFromDistance(point : {x : number, y:number}){
          let xMargin = point.x - Shake.point.x;
          let yMargin = point.y - Shake.point.y;
          return  Math.sqrt(xMargin * xMargin + yMargin * yMargin);
      };
}

let  shake = new Shake("蛇");
let  an = new  AnimalClass("动物");

shake.move();
shake.animalName = "子彬";
console.log(shake.animalName);

//抽象类 是不允许被实例化的：
abstract class DefaultPersion {

      //抽象方法
      abstract makeSound():void;
      move():void{
          console.log('roaming the earch...');
      }
}

class DefaultSubPerson  extends DefaultPersion{
       makeSound() : void {
           console.log('sub  makeSound .....');
       };
}

let sub = new DefaultSubPerson();
sub.makeSound();
sub.move();


//4.类中抽取出接口
//e.g门是一个类，防盗门是门的子类。如果防盗门有一个报警器的功能，我们可以简单的给防盗门添加一个报警方法。
// 这时候如果有另一个类，车，也有报警器的功能，就可以考虑把报警器提取出来，作为一个接口，防盗门和车都去实现它

interface IAlarm {
     alert();
}

interface ILight extends IAlarm{

    ligintOffOrOn();
}

class  Door {
    
}

class SecurityDoor extends Door implements IAlarm{
      alert(){
          console.log("安全们具有报警器....");
      }
}

class Car implements IAlarm,ILight {
    alert(){
        console.log("汽车具有报警器....");
    }
    ligintOffOrOn(){
        console.log('Car light off');
    }
}

let c = new  Car();
c.alert();
let  s =  new  SecurityDoor();
s.alert();


